﻿using FluentParser.Expressions;
using FluentParser.Expressions.Rules.Composition;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace FluentParser.Tests.Expressions.Rules.Composition
{
    [TestClass]
    public class SurroundExpressionRuleTests
    {
        [TestMethod]
        public void ParseT_WhenParsingValidText_ShouldReturnTheCenterTokenValue()
        {
            Symbol center = "text";
            var surround = new SurroundExpressionRule<object>("(", center.ToExpr(), ")");
            ParsingResult<object> result = surround.Parse("(text)");

            var expected = "text";
            var actual = result.Value;

            Assert.AreEqual(expected, actual);
            result.AssertLength("(text)");
        }

        [TestMethod]
        public void ParseT_WhenParsingInvalidLeftToken_ShouldReturnNull()
        {
            Symbol center = "text";
            var surround = new SurroundExpressionRule<object>("(", center.ToExpr(), ")");

            var expected = (ParsingResult<object>)null;
            var actual = surround.Parse("[text)");

            Assert.AreEqual(expected, actual);
        }

        [TestMethod]
        public void ParseT_WhenParsingInvalidCenterToken_ShouldReturnNull()
        {
            Symbol center = "text";
            var surround = new SurroundExpressionRule<object>("(", center.ToExpr(), ")");

            var expected = (ParsingResult<object>)null;
            var actual = surround.Parse("(SomethingElse)");

            Assert.AreEqual(expected, actual);
        }

        [TestMethod]
        public void ParseT_WhenParsingInvalidRightToken_ShouldReturnNull()
        {
            Symbol center = "text";
            var surround = new SurroundExpressionRule<object>("(", center.ToExpr(), ")");

            var expected = (ParsingResult<object>)null;
            var actual = surround.Parse("(text]");

            Assert.AreEqual(expected, actual);
        }

        [TestMethod]
        public void ParseNodeT_WhenParsingValidText_ShouldReturnTheCenterTokenValue()
        {
            Symbol center = "text";
            var surround = new SurroundExpressionRule<object>("(", center.ToExpr(), ")");
            ParsingNodeResult node = surround.ParseNode("(text)");

            string expected = "text";
            string actual = node.Value as string;

            Assert.AreEqual(expected, actual);
            node.AssertLength("(text)");
            node.AssertExploredLength("(text)");

            // Children check
            node.AssertChildren(
                true, // "("
                true, // "text"
                true); // ")"
        }

        [TestMethod]
        public void ParseNodeT_WhenParsingInvalidLeftToken_ShouldReturnNull()
        {
            Symbol center = "text";
            var surround = new SurroundExpressionRule<object>("(", center.ToExpr(), ")");
            ParsingNodeResult node = surround.ParseNode("[text)");

            string expected = null;
            string actual = node.Value as string;

            Assert.AreEqual(expected, actual);
            Assert.IsFalse(node.IsSuccess);
            node.AssertLength("");
            node.AssertExploredLength("?");

            node.AssertChildren(
                false); // "("
        }

        [TestMethod]
        public void ParseNodeT_WhenParsingInvalidCenterToken_ShouldReturnNull()
        {
            Symbol center = "text";
            var surround = new SurroundExpressionRule<object>("(", center.ToExpr(), ")");
            ParsingNodeResult node = surround.ParseNode("(SomethingElse)");

            string expected = null;
            string actual = node.Value as string;

            Assert.AreEqual(expected, actual);
            node.AssertLength("");
            node.AssertExploredLength("(?");

            node.AssertChildren(
                true, // "("
                false); // "text"
        }

        [TestMethod]
        public void ParseNodeT_WhenParsingInvalidRightToken_ShouldReturnNull()
        {
            Symbol center = "text";
            var surround = new SurroundExpressionRule<object>("(", center.ToExpr(), ")");
            ParsingNodeResult node = surround.ParseNode("(text]");

            string expected = null;
            string actual = node.Value as string;

            Assert.IsFalse(node.IsSuccess);
            Assert.AreEqual(expected, actual);
            node.AssertLength("");
            node.AssertExploredLength("(text?");

            node.AssertChildren(
                true, // "("
                true, // "text"
                false); // ")"
        }
    }
}
